﻿namespace Nomo.UnityCoreModule
{
    /// <summary>
    /// 为 <see cref="UnityEngine.GameObject"/> 类的实例提供扩展方法。
    /// </summary>
    public static class GameObjectExtension
    {
        /// <summary>
        /// 从游戏物体上获取指定类型组件。
        /// </summary>
        /// <param name="gameObject">这个游戏物体。</param>
        /// <param name="result">如果游戏物体上挂载有指定类型的组件，则为该组件；否则为 <see langword="null"/> .</param>
        /// <typeparam name="TComponent">要获取的组件的类型。</typeparam>
        /// <returns>如果游戏物体上挂载有指定类型的组件，则为 <see langword="true"/> ，否则为 <see langword="false"/> .</returns>
        public static bool TryGetComponent<TComponent>(this UnityEngine.GameObject gameObject, out TComponent result)
        {
            return (result = gameObject.GetComponent<TComponent>()) != null;
        }

        /// <summary>
        /// 从组件所在的游戏物体上获取指定类型组件。
        /// </summary>
        /// <param name="component">这个组件。</param>
        /// <param name="result">如果组件所在的游戏物体上挂载有指定类型的组件，则为该组件；否则为 <see langword="null"/> .</param>
        /// <typeparam name="TComponent">要获取的组件的类型。</typeparam>
        /// <returns>如果组件所在的游戏物体上挂载有指定类型的组件，则为 <see langword="true"/> ，否则为 <see langword="false"/> .</returns>
        public static bool TryGetComponent<TComponent>(this UnityEngine.Component component, out TComponent result)
        {
            switch (component)
            {
                case TComponent tComponent:
                    result = tComponent;
                    return true;
                default:
                    return (result = component.GetComponent<TComponent>()) != null;
            }
        }

        /// <summary>
        /// 从游戏物体上获取指定类型组件，如果没有，则向游戏物体添加一个这样的组件并将其返回。
        /// </summary>
        /// <param name="gameObject">这个游戏物体。</param>
        /// <typeparam name="TComponent">要获取的组件的类型。</typeparam>
        /// <returns>这个游戏物体上的指定类型的组件。</returns>
        public static TComponent GetOrAddComponent<TComponent>(this UnityEngine.GameObject gameObject) where TComponent : UnityEngine.Component
        {
            var tComponent = gameObject.GetComponent<TComponent>();
            if (tComponent == null)
            {
                tComponent = gameObject.AddComponent<TComponent>();
            }
            return tComponent;
        }

        /// <summary>
        /// 从组件所在的游戏物体上获取指定类型组件，如果没有，则向组件所在的游戏物体上添加一个这样的组件并将其返回。
        /// </summary>
        /// <param name="component">这个组件。</param>
        /// <typeparam name="TComponent">要获取的组件的类型。</typeparam>
        /// <returns>如果这个组件是 <typeparamref name="TComponent"/> 类型，则返回它本身；否则返回这个组件所在的游戏物体上的指定类型的组件。</returns>
        public static TComponent GetOrAddComponent<TComponent>(this UnityEngine.Component component) where TComponent : UnityEngine.Component
        {
            if (component is TComponent tComponent)
            {
                return tComponent;
            }
            tComponent = component.GetComponent<TComponent>();
            if (tComponent == null)
            {
                tComponent = component.gameObject.AddComponent<TComponent>();
            }
            return tComponent;
        }

        /// <summary>
        /// 设置界面物体的透明度。
        /// </summary>
        /// <param name="gameObject">界面物体。</param>
        /// <param name="alpha">要设置的透明度。</param>
        public static void SetAlpha(UnityEngine.GameObject gameObject, float alpha)
        {
            var canvasGroup = gameObject.GetComponent<UnityEngine.CanvasGroup>();
            if (canvasGroup == null)
            {
                canvasGroup = gameObject.AddComponent<UnityEngine.CanvasGroup>();
            }
            canvasGroup.alpha = UnityEngine.Mathf.Clamp01(alpha);
        }
    }
}
